﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Taxhui.Utils.Network.Tcp;
using Taxhui.Utils.Network.Tcp.NetSession;
using Taxhui.Utils.Network.Tcp.TcpConfig;
using Models;
using Newtonsoft.Json;

namespace Client.Common
{
    public class NetClient
    {
        public static ClientAgent _client;
        public static bool Connected = false;
        private Dictionary<string, Action<RetModel>> _callbackQueue = new Dictionary<string, Action<RetModel>>();
        private Action succCallback;
        private Action failCallback;

        #region 初始化客户端

        public void InitClient(string ip, int port, Action success, Action fail)
        {
            succCallback = success;
            failCallback = fail;
            ClientConfig cfg = new ClientConfig
            {
                AutoHeartBeat = true,
                CheckDisconnect = true,
                CheckDisconnectTimeout = 15,
                CompressTransferFromPacket = true,
                KeepAlive = true,
                KeepAliveInterval = 5000,
                KeepAliveSpanTime = 5000,
                NoDelay = true,
                ReceiveBufferSize = 8192,
                ReceiveTimeout = TimeSpan.Zero,
                SendBufferSize = 8192,
                SendTimeout = TimeSpan.Zero
            };
            _client = TcpFactory.CreateClientAgent(SessionType.Packet, cfg, Client_Event);
            _client.ConnectToServer(ip, port);
        }

        #endregion 初始化客户端

        #region 接收数据事件

        private void Client_Event(CompleteNotify e, Session session)
        {
            switch (e)
            {
                case CompleteNotify.OnConnected:
                    succCallback?.Invoke();
                    _callbackQueue.Clear();
                    Connected = true;
                    break;

                case CompleteNotify.OnSend:
                    break;

                case CompleteNotify.OnDataReceiveing:
                    break;

                case CompleteNotify.OnDataReceived:
                    HandleData(session.CompletedBuffer);
                    break;

                case CompleteNotify.OnClosed:
                    failCallback?.Invoke();
                    _callbackQueue.Clear();
                    Connected = false;
                    if (Comm.Running)
                        _client.ConnectToServer(Comm.CFG.ServerAddr, Comm.CFG.ServerPort);
                    break;

                default:
                    break;
            }
        }

        #endregion 接收数据事件

        #region 处理收到数据

        private async void HandleData(byte[] data)
        {
            if (data is null)
                return;
            var x = await Task.Run(() =>
            {
                try
                {
                    RetModel rm = JsonConvert.DeserializeObject<RetModel>(Encoding.UTF8.GetString(data));
                    if (_callbackQueue.Keys.Contains(rm.ReqID))
                        return rm;
                    return null;
                }
                catch (Exception)
                {
                }
                return null;
            });
            if (x != null)
            {
                var cb = _callbackQueue[x.ReqID];
                _callbackQueue.Remove(x.ReqID);
                cb(x);
            }
        }

        #endregion 处理收到数据

        #region 发送数据

        public void Send(Dictionary<string, object> data, Action<RetModel> callback)
        {
            if (!Connected)
                return;
            try
            {
                string reqId = data["reqId"].ToString();
                _callbackQueue.Add(reqId, callback);
                string jStr = JsonConvert.SerializeObject(data);
                byte[] bData = Encoding.UTF8.GetBytes(jStr);
                _client.Broadcast(bData);
            }
            catch (Exception)
            {
            }
        }

        #endregion 发送数据
    }
}